use std::borrow::Cow;

use serde::Serialize;
use thiserror::Error;
pub type IoErr = std::io::Error;

#[derive(Debug, Error)]
pub enum AppErr {

    #[error("io:{0}")]
    Io(#[from] IoErr),

    #[error("{0}")]
    Custom(Cow<'static, str>),

    #[error("{0}")]
    Proto(&'static str),

    #[error("serial:{0}")]
    Serial(#[from] tokio_serial::Error),
}

pub fn new_static_err<T>(msg: &'static str) -> Result<T, AppErr> {
    Err(AppErr::Custom(Cow::Borrowed(msg)))
}

pub fn new_err<T>(msg: String) -> Result<T, AppErr> {
    Err(AppErr::Custom(Cow::Owned(msg)))
}

pub fn new_proto_err<T>(msg: &'static str) -> Result<T, AppErr> {
    Err(AppErr::Proto(msg))
}

impl Serialize for AppErr {

    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer {
        let msg = self.to_string();
        serializer.serialize_str(&msg)
    }
}






